﻿#pragma once
#include "XyNet/Channel/Connection/RpcDataStream.h"
#include <boost/asio.hpp>

namespace XyNet
{
	class RpcEndpoint;
	class RpcSocketChannel;

	/// rpc连接，处理底层数据收发
	class XYNET_API RpcConnection : public enable_shared_from_this<RpcConnection>, noncopyable
	{
	public:
		/// 数据处理器，可以设置不同的处理函数来处理传输字节流
		typedef function<void(const Bytes&)> DataHandler;

	public:
		RpcConnection(RpcSocketChannel* socketChannel);
		virtual ~RpcConnection();

		/// 是否连接完成
		inline bool isConnectComplete() const { return _connectComplete; }

		/// 获取最大每秒读入消息数量
		inline int getMaxReadMessageCountPerSecond() const { return _maxReadMessageCountPerSecond; }
		/// 获取最大每秒写入消息数量
		inline int getMaxWriteMessageCountPerSecond() const { return _maxWriteMessageCountPerSecond; }
		/// 获取最大每秒读入字节
		inline int getMaxReadBytesPerSecond() const { return _maxReadBytesPerSecond; }
		/// 获取最大每秒写入字节
		inline int getMaxWriteBytesPerSecond() const { return _maxWriteBytesPerSecond; }

		/// 开始验证连接，完成后进行读写循环
		virtual void start();
		/// 写入数据
		virtual void write(const Bytes& data);

	protected:
		/// 读取数据
		virtual void read();

		/// 获取套接字通道
		shared_ptr<RpcSocketChannel> getSocketChannel();
		/// 插入写入数据缓存
		void pushCacheWriteData(const Bytes& data);
		/// 设置准备完成
		void setConnectComplete();

		/// 异步写入
		void asyncWrite(const Bytes& data);
		/// 异步读取
		void asyncRead(const DataHandler& handler);

	private:
		/// 写下一个数据。一个连接同一时间只能进行一次写入
		void writeNext();
		/// 读下一个数据。当发生异常中断读写循环时，处理完错误需要继续读取时才能调用。一个连接同一时间只能进行一次读取
		void readNext();

		/// 处理写入数据
		void handleWrite(const boost::system::error_code& error);
		/// 写入数据片段
		void writeSegment(int offset);
		/// 处理写入数据片段
		void handleWriteSegment(const boost::system::error_code& error, int offset);
		/// 处理写入计时器
		static void handleWriteTimer(weak_ptr<RpcConnection> weakConnection,
			const boost::system::error_code& error);
		/// 处理写入计时器
		static void handleWriteTimer(weak_ptr<RpcConnection> weakConnection,
			const boost::system::error_code& error, int offset);

		/// 处理读取大小
		void handleReadSize(const boost::system::error_code& error, const DataHandler& handler);
		/// 处理读取数据
		void handleReadData(const boost::system::error_code& error, const DataHandler& handler);
		/// 读取数据片段
		void readSegment(int offset, const DataHandler& handler);
		/// 处理读取数据片段
		void handleReadSegment(const boost::system::error_code& error, int offset, const DataHandler& handler);
		/// 处理读取计时器
		static void handleReadTimer(weak_ptr<RpcConnection> weakConnection,
			const boost::system::error_code& error);
		/// 处理读取计时器
		static void handleReadTimer(weak_ptr<RpcConnection> weakConnection,
			const boost::system::error_code& error, int offset, const DataHandler& handler);

		/// 处理连接密钥
		void handleReadKey(const Bytes& data);

		/// 开始秒计时器
		void startSecondTimer();
		/// 处理秒计时器
		static void handleSecondTimer(weak_ptr<RpcConnection> weakConnection,
			const boost::system::error_code& error);

		/// 套接字通道处理连接数据
		static void socketChannelHandleConnectionData(
			weak_ptr<RpcSocketChannel> weakSocketChannel, const Bytes& data);

	private:
		/// 所属套接字通道
		weak_ptr<RpcSocketChannel> _weakSocketChannel;

		/// 读取流
		RpcDataStream _readStream;
		/// 写入流队列
		deque<RpcDataStream> _writeStreamDeque;
		/// 写入流
		RpcDataStream _writeStream;
		/// 互斥量strand
		boost::asio::io_service::strand _strand;
		/// 读计时器
		unique_ptr<boost::asio::deadline_timer> _readTimer;
		/// 写计时器
		unique_ptr<boost::asio::deadline_timer> _writeTimer;

		/// 秒计时器（统计用）
		unique_ptr<boost::asio::deadline_timer> _secondTimer;
		/// 每秒读取消息数量
		int _readMessageCountPerSecond;
		/// 每秒写入消息数量
		int _writeMessageCountPerSecond;
		/// 最大每秒读取消息数量
		int _maxReadMessageCountPerSecond;
		/// 最大每秒写入消息数量
		int _maxWriteMessageCountPerSecond;
		/// 每秒读取字节
		int _readBytesPerSecond;
		/// 每秒写入字节
		int _writeBytesPerSecond;
		/// 最大每秒读取字节
		int _maxReadBytesPerSecond;
		/// 最大每秒写入字节
		int _maxWriteBytesPerSecond;

		/// 缓存消息（准备完成前暂时保存消息）
		vector<Bytes> _cachedWriteData;
		/// 是否准备好读写循环（是否交换好加密或非加密密钥，连接是否完成）
		bool _connectComplete;
	};
}